/**   
* 所属公司：稻普控股集团
* @Title: RedisObjectClient.java 
* @Package com.base.commpent
* @Description: redis基本操作
* @author xiongxiaotun
* @date 2017年3月24日 下午12:55:24 
* @version V1.0   
*/
package com.zjdiepu.www.commpent;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.stereotype.Component;

import com.zjdiepu.www.base.core.ParentModel;
import com.zjdiepu.www.common.consts.RedisKeyPrefix;

/**
 * 项目名称：dpqc-parent-manager-base <br/> 
 * 类名称：RedisObjectClient <br/>  
 * 类描述： redis缓存对象<br/>    
 * 创建人：xiongxiaotun <br/> 
 * 创建时间：2017年5月16日 下午4:33:34  <br/>   
 * 修改人：xiongxiaotun <br/> 
 * 修改时间：2017年5月16日 下午4:33:34   <br/>  
 * 修改备注：    <br/> 
 * @version V1.0   <br/>
 */
@Component
public class RedisObjectClient {

	@Autowired
	protected RedisCache redisCache;
	
	public <T> T execute(RedisCallback<T> callback){
		return redisCache.execute(callback);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: expire  <br/>
	 * @Description: 缓存并设置过期时间（单位秒） <br/>
	 * @param key
	 * @param value
	 * @param options
	 * @version V1.0  <br/>
	 */
	public void expire(String key, long timeout, String... options) {
		if(StringUtils.isBlank(key)) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		redisCache.expire(realKey, timeout, TimeUnit.SECONDS);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: putExpire  <br/>
	 * @Description: 缓存并设置过期时间（单位秒） <br/>
	 * @param key
	 * @param value
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void putExpire(String key, T value, long timeout, String... options) {
		if(StringUtils.isBlank(key) || value == null) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		redisCache.put(realKey, value, timeout, TimeUnit.SECONDS);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: put  <br/>
	 * @Description: 缓存 <br/>
	 * @param key
	 * @param value
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void put(String key, T value, String... options) {
		if(StringUtils.isBlank(key) || value == null) {
			return;
		}
		redisCache.put(RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options), value);
	}

	/**
	 * @author xiongxiaotun <br/>
	 * @Title: get  <br/>
	 * @Description: 获取  <br/>
	 * @param key
	 * @param options
	 * @return
	 * @version V1.0  <br/>
	 */
	@SuppressWarnings("unchecked")
	public <T> T get(String key, String... options) {
		if (StringUtils.isBlank(key)) {
			return null;
		}
		
		return (T)redisCache.get(RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options));
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: del  <br/>
	 * @Description: 移除 <br/>
	 * @param key
	 * @param options
	 * @version V1.0  <br/>
	 */
	public void del(String key, String... options) {
		if (StringUtils.isBlank(key)) {
			return;
		}
		redisCache.del(RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options));
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: cacheEntity  <br/>
	 * @Description: 缓存单个对象 <br/>
	 * @param entity
	 * @version V1.0  <br/>
	 */
	public <T extends ParentModel> void cacheEntity(T entity) {
		if(null == entity || StringUtils.isBlank(entity.getId())){
			return;
		}
		redisCache.put(RedisKeyPrefix.ENTTTY_PREFIX + entity.getClass().getSimpleName() + entity.getId(), entity);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: getCachedEntity  <br/>
	 * @Description: 缓存对象  <br/>
	 * @param id
	 * @param clazz
	 * @return
	 * @version V1.0  <br/>
	 */
	@SuppressWarnings("unchecked")
	public <T extends ParentModel> T getCachedEntity(String id, Class<T> clazz) {
		if (StringUtils.isBlank(id) || null == clazz) {
			return null;
		}
		
		return (T)redisCache.get(RedisKeyPrefix.ENTTTY_PREFIX + clazz.getSimpleName() + id);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: removeCachedEntity  <br/>
	 * @Description: 移除缓存 <br/>
	 * @param id
	 * @param clazz
	 * @version V1.0  <br/>
	 */
	public <T extends ParentModel> void removeCachedEntity(String id, Class<T> clazz) {
		if (StringUtils.isBlank(id) || null == clazz) {
			return;
		}
		redisCache.del(RedisKeyPrefix.ENTTTY_PREFIX + clazz.getSimpleName() + id);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: cacheList  <br/>
	 * @Description: 缓存多个对象 <br/>
	 * @param entitys
	 * @param clazz
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T extends ParentModel> void cacheList(List<T> entitys, Class<T> clazz, String... options) {
		if(clazz == null){
			return;
		}
		String realKey = RedisKeyPrefix.LIST_PREFIX + clazz.getSimpleName() + getKey(options);
		if(CollectionUtils.isEmpty(entitys)) {
			redisCache.del(realKey);
			return;
		}
		redisCache.put(realKey, entitys);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: getCachedList  <br/>
	 * @Description: 获取缓存对象  <br/>
	 * @param clazz
	 * @param options
	 * @return
	 * @version V1.0  <br/>
	 */
	@SuppressWarnings("unchecked")
	public <T extends ParentModel> List<T> getCachedList(Class<T> clazz, String... options) {
		if ( null == clazz) {
			return null;
		}
		return (List<T>)redisCache.get(RedisKeyPrefix.LIST_PREFIX + clazz.getSimpleName() + getKey(options));
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: removeCachedList  <br/>
	 * @Description: 移除缓存 <br/>
	 * @param clazz
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T extends ParentModel> void removeCachedList(Class<T> clazz, String... options) {
		if (null == clazz) {
			return;
		}
		redisCache.del(RedisKeyPrefix.LIST_PREFIX + clazz.getSimpleName() + getKey(options));
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: getKey  <br/>
	 * @Description: 获取key<br/>
	 * @param options
	 * @return
	 * @version V1.0  <br/>
	 */
	private String getKey(String... options){
		if(options == null || options.length == 0) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		for(String option : options) {
			if(StringUtils.isNotBlank(option)) {
				sb.append("_").append(option);
			}
		}
		return sb.toString();
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: hDel  <br/>
	 * @Description: 删除缓存 <br/>
	 * @param key
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void hDels(String key,String... options) {
		if(StringUtils.isBlank(key)) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		redisCache.hDels(realKey);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: hDel  <br/>
	 * @Description: 删除缓存 <br/>
	 * @param key
	 * @param field
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void hDel(String key,String field, String... options) {
		if(StringUtils.isBlank(key) || StringUtils.isBlank(field)) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		redisCache.hDel(realKey, field);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: hSet  <br/>
	 * @Description: 缓存 <br/>
	 * @param key
	 * @param field
	 * @param value
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void hSet(String key,String field, T value, String... options) {
		if(StringUtils.isBlank(key) || StringUtils.isBlank(field) || value == null) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		redisCache.hSet(realKey, field, value);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: hSet  <br/>
	 * @Description: 缓存 <br/>
	 * @param key
	 * @param field
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> T hGet(String key,String field, String... options) {
		if(StringUtils.isBlank(key) || StringUtils.isBlank(field)) {
			return null;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		T hGet = redisCache.hGet(realKey, field);
		return hGet;
	}
	
//	===========================================================回调使用===================================
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: expire  <br/>
	 * @Description: 缓存并设置过期时间（单位秒） <br/>
	 * @param key
	 * @param value
	 * @param options
	 * @version V1.0  <br/>
	 */
	public void expire(RedisConnection redisConnection, String key, long timeout, String... options) {
		if(StringUtils.isBlank(key)) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		byte[] keyb = realKey.getBytes();
		redisConnection.expire(keyb, timeout);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: putExpire  <br/>
	 * @Description: 缓存并设置过期时间（单位秒） <br/>
	 * @param key
	 * @param value
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void putExpire(RedisConnection redisConnection, String key, T value, long timeout, String... options) {
		if(StringUtils.isBlank(key) || value == null) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		byte[] keyb = realKey.getBytes();
		redisConnection.setEx(keyb, timeout, RedisCache.toByteArray(value));
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: put  <br/>
	 * @Description: 缓存 <br/>
	 * @param key
	 * @param value
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void put(RedisConnection redisConnection, String key, T value, String... options) {
		if(StringUtils.isBlank(key) || value == null) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		byte[] keyb = realKey.getBytes();
		redisConnection.set(keyb, RedisCache.toByteArray(value));
	}

	/**
	 * @author xiongxiaotun <br/>
	 * @Title: get  <br/>
	 * @Description: 获取  <br/>
	 * @param key
	 * @param options
	 * @return
	 * @version V1.0  <br/>
	 */
	@SuppressWarnings("unchecked")
	public <T> T get(RedisConnection redisConnection, String key, String... options) {
		if (StringUtils.isBlank(key)) {
			return null;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		byte[] keyb = realKey.getBytes();
		byte[] value = redisConnection.get(keyb);
		if(value == null) {
			return null;
		}
		return (T)RedisCache.toObject(value);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: del  <br/>
	 * @Description: 移除 <br/>
	 * @param key
	 * @param options
	 * @version V1.0  <br/>
	 */
	public void del(RedisConnection redisConnection, String key, String... options) {
		if (StringUtils.isBlank(key)) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		byte[] keyb = realKey.getBytes();
		redisConnection.del(keyb);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: cacheEntity  <br/>
	 * @Description: 缓存单个对象 <br/>
	 * @param entity
	 * @version V1.0  <br/>
	 */
	public <T extends ParentModel> void cacheEntity(RedisConnection redisConnection, T entity) {
		if(null == entity || StringUtils.isBlank(entity.getId())) {
			return;
		}
		String realKey = RedisKeyPrefix.ENTTTY_PREFIX + entity.getClass().getSimpleName() + entity.getId();
		byte[] keyb = realKey.getBytes();
		redisConnection.set(keyb, RedisCache.toByteArray(entity));
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: getCachedEntity  <br/>
	 * @Description: 缓存对象  <br/>
	 * @param id
	 * @param clazz
	 * @return
	 * @version V1.0  <br/>
	 */
	@SuppressWarnings("unchecked")
	public <T extends ParentModel> T getCachedEntity(RedisConnection redisConnection, String id, Class<T> clazz) {
		if (StringUtils.isBlank(id) || null == clazz) {
			return null;
		}
		String realKey = RedisKeyPrefix.ENTTTY_PREFIX + clazz.getSimpleName() + id;
		byte[] keyb = realKey.getBytes();
		byte[] value = redisConnection.get(keyb);
		if(value == null) {
			return null;
		}
		return (T)RedisCache.toObject(value);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: removeCachedEntity  <br/>
	 * @Description: 移除缓存 <br/>
	 * @param id
	 * @param clazz
	 * @version V1.0  <br/>
	 */
	public <T extends ParentModel> void removeCachedEntity(RedisConnection redisConnection, String id, Class<T> clazz) {
		if (StringUtils.isBlank(id) || null == clazz) {
			return;
		}
		String realKey =RedisKeyPrefix.ENTTTY_PREFIX + clazz.getSimpleName() + id;
		byte[] keyb = realKey.getBytes();
		redisConnection.del(keyb);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: cacheList  <br/>
	 * @Description: 缓存多个对象 <br/>
	 * @param entitys
	 * @param clazz
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T extends ParentModel> void cacheList(RedisConnection redisConnection, List<T> entitys, Class<T> clazz, String... options) {
		if(clazz == null){
			return;
		}
		String realKey = RedisKeyPrefix.LIST_PREFIX + clazz.getSimpleName() + getKey(options);
		byte[] keyb = realKey.getBytes();
		if(CollectionUtils.isEmpty(entitys)) {
			redisConnection.del(keyb);
			return;
		}
		redisConnection.set(keyb, RedisCache.toByteArray(entitys));
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: getCachedList  <br/>
	 * @Description: 获取缓存对象  <br/>
	 * @param clazz
	 * @param options
	 * @return
	 * @version V1.0  <br/>
	 */
	@SuppressWarnings("unchecked")
	public <T extends ParentModel> List<T> getCachedList(RedisConnection redisConnection, Class<T> clazz, String... options) {
		if ( null == clazz) {
			return null;
		}
		String realKey = RedisKeyPrefix.LIST_PREFIX + clazz.getSimpleName() + getKey(options);
		byte[] keyb = realKey.getBytes();
		byte[] value = redisConnection.get(keyb);
		if(value == null) {
			return null;
		}
		return (List<T>)RedisCache.toObject(value);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: removeCachedList  <br/>
	 * @Description: 移除缓存 <br/>
	 * @param clazz
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T extends ParentModel> void removeCachedList(RedisConnection redisConnection, Class<T> clazz, String... options) {
		if (null == clazz) {
			return;
		}
		String realKey = RedisKeyPrefix.LIST_PREFIX + clazz.getSimpleName() + getKey(options);
		byte[] keyb = realKey.getBytes();
		redisConnection.del(keyb);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: hDel  <br/>
	 * @Description: 删除缓存 <br/>
	 * @param redisConnection
	 * @param key
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void hDels(RedisConnection redisConnection, String key,String... options) {
		if(StringUtils.isBlank(key)) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		byte[] keyb = realKey.getBytes();
		redisConnection.del(keyb);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: hDel  <br/>
	 * @Description: 删除缓存 <br/>
	 * @param redisConnection
	 * @param key
	 * @param field
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void hDel(RedisConnection redisConnection, String key,String field, String... options) {
		if(StringUtils.isBlank(key) || StringUtils.isBlank(field)) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		byte[] keyb = realKey.getBytes();
		byte[] fieldb = field.getBytes();
		redisConnection.hDel(keyb, fieldb);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: hSet  <br/>
	 * @Description: 缓存 <br/>
	 * @param redisConnection
	 * @param key
	 * @param field
	 * @param value
	 * @param options
	 * @version V1.0  <br/>
	 */
	public <T> void hSet(RedisConnection redisConnection, String key,String field, T value, String... options) {
		if(StringUtils.isBlank(key) || StringUtils.isBlank(field) || value == null) {
			return;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		byte[] keyb = realKey.getBytes();
		byte[] fieldb = field.getBytes();
		byte[] valueb = RedisCache.toByteArray(value);
		redisConnection.hSet(keyb, fieldb, valueb);
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title: hSet  <br/>
	 * @Description: 缓存 <br/>
	 * @param redisConnection
	 * @param key
	 * @param field
	 * @param options
	 * @version V1.0  <br/>
	 */
	@SuppressWarnings("unchecked")
	public <T> T hGet(RedisConnection redisConnection, String key,String field, String... options) {
		if(StringUtils.isBlank(key) || StringUtils.isBlank(field)) {
			return null;
		}
		String realKey = RedisKeyPrefix.SIMPLE_PREFIX + key + getKey(options);
		byte[] keyb = realKey.getBytes();
		byte[] fieldb = field.getBytes();
		byte[] value = redisConnection.hGet(keyb, fieldb);
		if(value == null) {
			return null;
		}
		return (T)RedisCache.toObject(value);
	}
}
